[小ネタ]Lambda-backed custom resourcesで全リージョンのデフォルトVPCを削除する
新しいAWSアカウントを作成するタイミングで全リージョンのデフォルトVPCを削除したい方向け
こんにちは、おんづか(@onzuka_muscle)です!
こちらのブログを参考にアカウントが特定OUに所属したタイミングでLambdaを実行し、デフォルトVPCを削除してみました。
注意点
- 作成したばかりのAWSアカウントを想定しています
- そのためデフォルトVPCに紐づいたリソースをユーザーが作成していると本Lambdaは失敗します
- Lambdaが実行された後もLambda , IAMロール , CloudWatch Logsといったリソースは残ります
- 必要に応じて削除してください
- あくまでサンプルコードです
- エラーハンドリング・ロギングについてはそこそこなので必要に応じてカスタマイズください
テンプレート
AWSTemplateFormatVersion: "2010-09-09" # ------------------------------------------------------------# # デフォルト VPC を削除する Lambda-backed custom resources # ------------------------------------------------------------# Parameters: RoleName: Type: String FunctionName: Type: String Resources: # ------------------------------------------------------------# # Lambda-backed custom resources # ------------------------------------------------------------# DeleteDefaultVPC: Type: Custom::DeleteDefaultVPC Properties: ServiceToken: !GetAtt "LambdaFunction.Arn" # ------------------------------------------------------------# # Lambda 関数 # ------------------------------------------------------------# LambdaFunction: Type: AWS::Lambda::Function Properties: FunctionName: !Ref FunctionName Description: Lambda for delete default VPC Role: !GetAtt "LambdaExecutionRole.Arn" Runtime: "python3.8" Handler: index.lambda_handler Timeout: 120 Code: ZipFile: | import boto3 import json import cfnresponse from logging import getLogger, INFO logger = getLogger() logger.setLevel(INFO) def delete_default_vpc(event, context): region_list = [] ec2_client = boto3.client('ec2') regions = ec2_client.describe_regions() for r in range(0, len(regions['Regions'])): region_name = regions['Regions'][r]['RegionName'] region_list.append(region_name) for region in region_list: try: client = boto3.client('ec2', region_name=region) ec2 = boto3.resource('ec2', region_name=region) vpcs = get_default_vpcs(client) except boto3.exceptions.Boto3Error as e: logger.info(e) exit(1) else: for vpc in vpcs: logger.info("\n" + "\n" + "REGION:" + region + "\n" + "VPC Id:" + vpc) del_igw(ec2, vpc) del_sub(ec2, vpc) del_vpc(ec2, vpc) def lambda_handler(event, context): if event['RequestType'] == 'Create': # Create時に実行したい処理 --> デフォルト VPC を削除する delete_default_vpc(event, context) cfnresponse.send(event, context, cfnresponse.SUCCESS, {'Response': 'Success'}) if event['RequestType'] == 'Delete': # Delete時に実行したい処理 --> 無し cfnresponse.send(event, context, cfnresponse.SUCCESS, {'Response': 'Success'}) if event['RequestType'] == 'Update': # Update時に実行したい処理 --> 無し cfnresponse.send(event, context, cfnresponse.SUCCESS, {'Response': 'Success'}) def get_default_vpcs(client): vpc_list = [] vpcs = client.describe_vpcs( Filters=[ { 'Name': 'isDefault', 'Values': [ 'true', ], }, ] ) vpcs_str = json.dumps(vpcs) resp = json.loads(vpcs_str) data = json.dumps(resp['Vpcs']) vpcs = json.loads(data) for vpc in vpcs: vpc_list.append(vpc['VpcId']) return vpc_list def del_igw(ec2, vpcid): vpc_resource = ec2.Vpc(vpcid) igws = vpc_resource.internet_gateways.all() if igws: for igw in igws: try: igw.detach_from_vpc( VpcId=vpcid ) igw.delete() except boto3.exceptions.Boto3Error as e: logger.info(e) def del_sub(ec2, vpcid): vpc_resource = ec2.Vpc(vpcid) subnets = vpc_resource.subnets.all() default_subnets = [ec2.Subnet(subnet.id) for subnet in subnets if subnet.default_for_az] if default_subnets: try: for sub in default_subnets: sub.delete() except boto3.exceptions.Boto3Error as e: logger.info(e) def del_vpc(ec2, vpcid): vpc_resource = ec2.Vpc(vpcid) try: vpc_resource.delete() except boto3.exceptions.Boto3Error as e: logger.info(e) logger.info("Please remove dependencies and delete VPC manually.") # ------------------------------------------------------------# # Lambda 関数用の IAM ロール # ------------------------------------------------------------# LambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Ref RoleName AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: "lambda.amazonaws.com" Action: "sts:AssumeRole" ManagedPolicyArns: - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" Policies: - PolicyName: DeleteDefaultVPCPolicy PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - "ec2:DescribeRegions" - "ec2:DescribeInternetGateways" - "ec2:DetachInternetGateway" - "ec2:DeleteInternetGateway" - "ec2:DescribeSubnets" - "ec2:DeleteSubnet" - "ec2:DescribeVpcs" - "ec2:DeleteVpc" Resource: "*"
動作確認
EC2 Global View
より確認しました。
Before
After
綺麗さっぱりになりました!
おわり
サンプルコードになりますが需要あるかなと思いブログにしました。
こちらのブログのようにCloudFormation StackSetsと組み合わせることで新しく作成したアカウントのデフォルトVPC削除を効率化できます。
誰かのお役に立てば嬉しいです。